using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace ICeFramework.Win.UI
{
    public enum Status { New, Processing, Error, Ok }
    public delegate void StatusClickEventHandler(object sender, StatusClickEventArgs e);
    public partial class StatusListView : ListView
    {
        public event StatusClickEventHandler StatusClick;

        private System.Windows.Forms.ListViewItem.ListViewSubItem sel_itm = null;
        private int status_itm = -1;
        private int status_col = 1;

        public int StatusItemIndex
        {
            get { return status_itm; }
            set { status_itm = value; }
        }

        public int StatusColumnIndex
        {
            get 
            {
                return status_col;
            }
            set 
            { 
                if ((value > 0) & (value < this.Columns.Count))
                    status_col = value;
            }
        }

        public void SetItemStatus(int ItemIndex, ItemStatus Status)
        {
            if (this.Items[ItemIndex] != null)
            {
                this.Items[ItemIndex].Selected = true;
                if (this.Items[ItemIndex].SubItems[status_col] != null)
                    this.Items[ItemIndex].SubItems[status_col].Tag = Status;
            }
        }

        public StatusListView()
        {
            InitializeComponent();
            this.DoubleBuffered = true;
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        }

        public void OnStatusClick(object sender, StatusClickEventArgs e)
        {
            if (StatusClick != null)
            {
                StatusClick(this, e);
            }
        }        

        private void StatusListView_DrawItem(object sender, DrawListViewItemEventArgs e)
        {
            Bitmap b = new Bitmap(e.Bounds.Width, e.Bounds.Height);
            Graphics g = Graphics.FromImage(b);

            if ((e.State & ListViewItemStates.Selected) != 0)
            {
                g.FillRectangle(Brushes.LightGray, e.Bounds);
                e.DrawFocusRectangle();
                if (e.ItemIndex == status_itm)
                {
                    g.DrawImage(imageList1.Images[2], e.Bounds.X + 2, 1, e.Bounds.Height - 2, e.Bounds.Height - 2);
                    Font f = new Font(this.Font.FontFamily, this.Font.Size, FontStyle.Bold);
                    g.DrawString(e.Item.Text, f, Brushes.Black, e.Bounds.X + e.Bounds.Height, 0);
                }
                else g.DrawString(e.Item.Text, this.Font, Brushes.Black, e.Bounds.X + e.Bounds.Height, 0);
            }
            else
                if ((e.ItemIndex == status_itm) & (status_itm >= 0))
                {
                    g.DrawImage(imageList1.Images[2], e.Bounds.X + 2, 1, e.Bounds.Height - 2, e.Bounds.Height - 2);
                    Font f = new Font(this.Font.FontFamily, this.Font.Size, FontStyle.Bold);
                    g.DrawString(GetText(e.Item.Text, f, this.Columns[0].Width), f, Brushes.Black, e.Bounds.X + e.Bounds.Height, 0);
                }
                else g.DrawString(GetText(e.Item.Text, this.Font, this.Columns[0].Width), this.Font, Brushes.Black, e.Bounds.X + e.Bounds.Height, 0);

            e.Graphics.DrawImage(b, e.Bounds.X, e.Bounds.Y);
        }

        private void StatusListView_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
        {
            e.DrawBackground();
            e.DrawText();
        }

        private void StatusListView_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
        {

            if (e.ColumnIndex > 0)
            {
                Bitmap b = new Bitmap(e.Bounds.Width, e.Bounds.Height);
                Graphics g = Graphics.FromImage(b);

                if (e.ColumnIndex == status_col)
                {
                    if (e.SubItem.Tag != null)
                    {
                        try
                        {
                            ItemStatus st = (ItemStatus)e.SubItem.Tag;
                            switch (st.Status)
                            {
                                case Status.Error:
                                    g.DrawImage(imageList1.Images[1], 2, 1, e.Bounds.Height - 2, e.Bounds.Height - 2);
                                    break;
                                case Status.New:
                                    g.DrawImage(imageList1.Images[3], 2, 1, e.Bounds.Height - 2, e.Bounds.Height - 2);
                                    break;
                                case Status.Ok:
                                    g.DrawImage(imageList1.Images[0], 2, 1, e.Bounds.Height - 2, e.Bounds.Height - 2);
                                    break;
                                case Status.Processing:
                                    g.DrawImage(imageList1.Images[4], 2, 1, e.Bounds.Height - 2, e.Bounds.Height - 2);
                                    break;
                            }
                        }
                        catch
                        {
                            g.DrawImage(imageList1.Images[3], 2, 1, e.Bounds.Height - 2, e.Bounds.Height - 2);
                        }
                    }
                    else g.DrawImage(imageList1.Images[3], 0, 2, e.Bounds.Height - 2, e.Bounds.Height - 2);
                }

                //if (e.Item.SubItems[status_col].Equals(sel_itm))
                if (e.SubItem.Equals(sel_itm))
                {
                    Font f = new Font(this.Font.FontFamily, this.Font.Size, FontStyle.Underline);
                    g.DrawString(GetText(e.SubItem.Text, f, this.Columns[status_col].Width), f, Brushes.Black, e.SubItem.Bounds.Height, 0);
                }
                else
                    g.DrawString(GetText(e.SubItem.Text, this.Font, this.Columns[e.ColumnIndex].Width), this.Font, Brushes.Black, e.SubItem.Bounds.Height, 0);

                e.Graphics.DrawImage(b, e.Item.SubItems[e.ColumnIndex].Bounds.X, e.Bounds.Y);
            }            
        }

        private void StatusListView_MouseMove(object sender, MouseEventArgs e)
        {
            ListViewItem itm = this.GetItemAt(e.X, e.Y);
            if (itm != null)
            {
                System.Windows.Forms.ListViewItem.ListViewSubItem si = itm.SubItems[status_col];
                if ((si != null) && (!si.Equals(sel_itm)))
                {
                    ItemStatus st = null;
                    if (sel_itm != null)
                        st = (ItemStatus)sel_itm.Tag;
                    if ((e.X >= si.Bounds.X) && (e.X <= si.Bounds.X + si.Bounds.Width) & ((st != null) && (st.Status == Status.Error)))
                    {
                        if (sel_itm != null)
                            Invalidate(sel_itm.Bounds);

                        sel_itm = si;
                        Invalidate(si.Bounds);
                    }
                    else
                    {
                        if (sel_itm != null)
                            Invalidate(sel_itm.Bounds);
                        sel_itm = null;
                    }
                }
                else
                {
                    //if (sel_itm != null)
                    //  Invalidate(sel_itm.Bounds);
                    //sel_itm = null;
                }

                if (si != null)
                    this.Cursor = Cursors.Hand;
                else this.Cursor = Cursors.Default;

            }
            else
            {
                if (sel_itm != null)
                    Invalidate(sel_itm.Bounds);
                sel_itm = null;
                this.Cursor = Cursors.Default;
            }
        }

        private void StatusListView_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.SelectedIndices.Count > 0)
                status_itm = this.SelectedIndices[0];
        }

        private void StatusListView_Click(object sender, EventArgs e)
        {
            if (sel_itm != null)
            {
                OnStatusClick(sender, new StatusClickEventArgs((ItemStatus)sel_itm.Tag));
            }
        }

        private string GetText(string Text, Font f, int width)
        {
            if (width > 20)
            {
                width -= 20;
                Graphics g = this.CreateGraphics();
                SizeF sf = g.MeasureString(Text, f);

                if (sf.Width > width)
                {
                    while ((sf.Width > width) & (Text.Length > 0))
                    {
                        Text = Text.Substring(0, Text.Length - 1);
                        sf = g.MeasureString(Text, f);
                    }
                    g.Dispose();
                    if (Text.Length > 0)
                        return Text.Substring(0, Text.Length) + "...";
                    else return "...";
                }
                else return Text;
            }
            else return "...";            
        }

        private void StatusListView_ColumnWidthChanging(object sender, ColumnWidthChangingEventArgs e)
        {
            //this.Columns[Columns.Count - 1].Width = -2;
            //e.Cancel = true;
        }

        private void StatusListView_Resize(object sender, EventArgs e)
        {
            if (this.Columns.Count > 0)
            {
                this.Columns[Columns.Count - 1].Width = -2;
            }
        }

        private void StatusListView_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
        {
            
            //this.Columns[Columns.Count - 1].Width = -2;
        }
    }

    public class StatusClickEventArgs : EventArgs
    {
        private ItemStatus status;

        public ItemStatus Status
        {
            get { return status; }
        }

        public StatusClickEventArgs(ItemStatus Status)
        {
            status = Status;
        }
    }

    public class ItemStatus
    {
        private Status stat;
        private Exception exc = null;

        public Status Status
        {
            get { return stat; }
        }

        public Exception ex
        {
            get { return exc; }
        }

        public ItemStatus(Status status)
        {
            stat = status;
            exc = null;
        }

        public ItemStatus(Exception ex)
        {
            stat = Status.Error;
            exc = ex;
        }
    }
}
